﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OrmSmackdown;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Data;
using Microsoft.SqlServer.Management.Trace;
using Microsoft.SqlServer.Management.Common;

namespace OrmSmackdownTests
{
    class CrudRunner
    {
        private ICrud _crud;
        private ILogger _logger;
        
        public CrudRunner(ICrud crud, ILogger logger)
        {
            _logger = logger;
            _crud = crud;
        }

        public void StartTracing(object o)
        {
            var tracer = o as TraceServer;
            while (tracer.Read())
            {
                try
                {
                    string traceType = tracer.GetValue(0).ToString();
                    if (traceType == "RPC:Completed" || traceType == "SQL:BatchCompleted")
                    {
                        _logger.WriteLine(tracer["TextData"].ToString());
                        _logger.WriteLine("======================");
                        _logger.WriteLine(string.Empty);
                    }
                }
                catch
                {
                    //does not container text data or text data is null.
                }
            }
        }

        public void CrudIt(IDbConnection conn)
        {
            TraceServer tracer = null;

            try
            {
                string traceConfiguration = string.Format(@"{0}\..\..\..\OrmSmackdownTests\SQLTracing\Standard.tdf", AppDomain.CurrentDomain.BaseDirectory);
                if (!System.IO.File.Exists(traceConfiguration))
                    traceConfiguration = string.Format(@"{0}\..\..\SQLTracing\Standard.tdf", AppDomain.CurrentDomain.BaseDirectory);

                if (System.IO.File.Exists(traceConfiguration))
                {
                    _logger.WriteLine("Using configuration file at: " + traceConfiguration);

                    tracer = new TraceServer();
                    ConnectionInfoBase ci = new SqlConnectionInfo("localhost");
                    ((SqlConnectionInfo)ci).UseIntegratedSecurity = true;

                    tracer.InitializeAsReader(ci, traceConfiguration);
                }
                else
                    _logger.WriteLine("Could not find SQL Server Trace Configuration File.");
            }
            catch (Exception exc)
            {
                tracer = null;
                _logger.WriteLine("SQL Server Profiling tools not found.  SQL Tracing not available.");
                _logger.WriteLine(exc.Message);
            }

            _logger.WriteLine(string.Format("Starting exercises on ORM: {0}  against a {1} connection", _crud.GetType().Namespace, conn.GetType().Name));

            if (tracer != null)
                new System.Threading.Thread(StartTracing).Start(tracer);

            try
            {
                Support.CleanDatabase(conn);

                _logger.Start("Inserting Record");

                var id = _crud.Create("Kevin", "Wolf", "kevinw@slsys.com");

                _logger.End("Inserting Record");

                _logger.Start("Reading Record");

                var person = _crud.Read(id);
                Assert.AreEqual(0, person.AddressList.Count());
                Assert.AreEqual(person.FirstName, "Kevin");
                Assert.AreEqual(person.LastName, "Wolf");
                Assert.AreEqual(person.Email, "kevinw@slsys.com");

                _logger.End("Reading Record");

                _logger.Start("Updating Record");

                _crud.Update(id, "Fred", "Flintstone", "fred.flintstone@bedrock.fl.us");

                var loadedPerson = _crud.Read(id);
                Assert.IsNotNull(loadedPerson);
                Assert.AreEqual(loadedPerson.FirstName, "Fred");
                Assert.AreEqual(loadedPerson.LastName, "Flintstone");
                Assert.AreEqual(loadedPerson.Email, "fred.flintstone@bedrock.fl.us");

                _logger.End("Updating Record");

                _logger.Start("Deleting Record");

                _crud.Delete(id);

                _logger.End("Deleting Record");

                Assert.IsNull(_crud.Read(id));
            }
            catch(Exception exc)
            {
                _logger.WriteLine(exc.Message);
                _logger.WriteLine(exc.StackTrace);
            }
            finally
            {
                if (tracer != null)
                {
                    tracer.Stop();
                    tracer.Close();
                    tracer.Dispose();
                }
            }
        }
    }
}
